package fi.foyt.cs.oauth.protectedresource;

import java.util.logging.Logger;

import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.ChallengeRequest;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.Form;
import org.restlet.data.Parameter;
import org.restlet.data.Status;
import org.restlet.ext.oauth.protectedresource.RemoteAuthorizer;
import org.restlet.ext.oauth.provider.OAuthError;
import org.restlet.security.User;
import org.restlet.util.Series;

import fi.foyt.cs.controller.OAuthController;
import fi.foyt.cs.persistence.domainmodel.oauth.AuthenticatedUser;
import fi.foyt.cs.persistence.domainmodel.oauth.AuthenticatedUserToken;

public class Authorizer extends RemoteAuthorizer {

  public Authorizer(String authorizationURI) {
    super(null, authorizationURI);
  }

  @Override
  protected boolean authorize(Request req, Response resp) {
    Logger log = Context.getCurrentLogger();
    log.info("Checking for param access_token");

    String accessToken = null;
    if (req.getChallengeResponse() != null) {
      // There is a Authorization header
      accessToken = req.getChallengeResponse().getRawValue();
      getLogger().info("Found Authorization header" + accessToken);
    }

    if (accessToken == null || accessToken.length() == 0) {
      ChallengeRequest cr = new ChallengeRequest(ChallengeScheme.HTTP_OAUTH, "oauth");
      Series<Parameter> parameters = new Form();
      parameters.add("error", OAuthError.ErrorCode.invalid_request.name());
      cr.setParameters(parameters);
      resp.getChallengeRequests().add(cr);
      resp.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
    } else {
      getLogger().info("Found Access Token " + accessToken);

      OAuthController oAuthController = new OAuthController();
      AuthenticatedUserToken authenticatedUserToken = oAuthController.findAuthenticatedUserTokenByToken(accessToken);

      if (authenticatedUserToken != null) {
        getLogger().info("Access Token is valid");
        AuthenticatedUser authenticatedUser = oAuthController.findAuthenticatedUserById(authenticatedUserToken.getAuthenticatedUserId());
        getLogger().info("Logged user: " + authenticatedUser.getUserId());
        User user = new User(authenticatedUser.getUserId(), accessToken);
        req.getClientInfo().setUser(user);
        req.getClientInfo().setAuthenticated(true);
        return true;
      } else {
        getLogger().info("Access Token is invalid");
        ChallengeRequest cr = new ChallengeRequest(ChallengeScheme.HTTP_OAUTH, "oauth");
        OAuthError.ErrorCode code = OAuthError.ErrorCode.invalid_token;
        Series<Parameter> parameters = new Form();
        parameters.add("error", code.name());
        resp.setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
        cr.setParameters(parameters);
        resp.getChallengeRequests().add(cr);
      }
    }
    return false;
  }
}
